#include <signal.h>
#include <dtalk/default_devInfo_provider.hpp>
#include "demo.hpp"
#include "BaseCmdParam.h"
#ifdef _REDIS_IMPL_
#include <simplemq/simplemq_redis.hpp>
#elif defined(_MQTT_IMPL_)
#include <simplemq/simplemq_mqtt.hpp>
#else
#error not define implementation type _MQTT_IMPL_ or _REDIS_IMPL_
#endif
/** 命令行参数解析器 */
class ClientConfig : public gdface::BaseClientConfig {
public:
	const std::string PARAM_USERNAME = "username";
	const std::string PARAM_PASSWORD = "password";
	const std::string PARAM_SAVE     = "save";
	std::string username;
	std::string password;
	bool savejson;
	bool needUsername;
	ClientConfig(int defaultPort,bool needUsername) :gdface::BaseClientConfig(defaultPort), needUsername(needUsername){
		if (needUsername) 
		{
			cmdparam.add<std::string>(PARAM_USERNAME, 'u', "username for authorization", false, "");
		}
		cmdparam.add<std::string>(PARAM_PASSWORD, 'a', "password for authorization", false, "");
		cmdparam.add<bool>(PARAM_SAVE,     's', "save Demo Menu JSON to File", false, "");
	}
	ClientConfig() : ClientConfig(0, false) {}
	~ClientConfig() = default;
	void afterParse() {
		gdface::BaseClientConfig::afterParse();
		if (needUsername)
		{
			username = cmdparam.get<std::string>(PARAM_USERNAME);
		}
		password = cmdparam.get<std::string>(PARAM_PASSWORD);
		savejson = cmdparam.get<bool>(PARAM_SAVE);
	}
};

static std::condition_variable should_exit;

static void sigint_handler(int) {
	should_exit.notify_all();
}
/**  定义为全局变量(单实例) */
static simplemq::ClientManager cmgr;

//************************************
// 删除 'regex' 字段用于 dengci 测试
// @param    const dtalk::item_ptr_type & item
// @return   void
//************************************
static void normalDemoMenu(const dtalk::item_ptr_type &item)
{
	item->fields.erase(__J_NAME(regex));

	for (auto itor = item->items.begin();itor < item->items.cend();++itor)
	{
		normalDemoMenu(itor->second);
	}
}

//************************************
// 保存菜单JSON数据到文本文件
// @param    const dtalk::menu_ptr_type & root
// @return   void
//************************************
static void saveDemoJson(const dtalk::menu_ptr_type &root)
{
	normalDemoMenu(root);
	auto jstr = root->toJson().dump(4);
	gdface::save_binary_file("demo_menu_json.txt", jstr.data(), jstr.size());
}


int main(int argc, char *argv[]) {
	std::shared_ptr<ClientConfig> param = 
		(cmgr.getImplType() == "REDIS")? std::make_shared<ClientConfig>(simplemq::DEFAULT_REDIS_PORT, false)
		                               : std::make_shared<ClientConfig>(simplemq::DEFAULT_MQTT_PORT, true );
	/** 解析命令行参数  */
	param->parse(argc, argv);

	auto config = std::make_shared<simplemq::mq_client_params>(param->host, param->port, param->password, param->username);
	/** 启动 demo 引擎 */
	dtalk::Demo demo(cmgr, config, std::make_shared<dtalk::DefaultDevInfoProvider>());
	if (param->savejson)
	{
		saveDemoJson(demo.root);
		return 0;
	}
	else
	{
		demo.start();
	}

	signal(SIGINT, &sigint_handler);
	std::mutex mtx;
	std::unique_lock<std::mutex> lock(mtx);
	should_exit.wait(lock);
	return 0;
}